# -*- coding:utf-8 -*-
# created on 2017/4/30
#

from mathsolver.functions.base import *
from mathsolver.functions.xiangliang.Vector_Fundamental import vector_xiangs
from sympy import Abs, cos


def xl_get_all_child(expr, func):
    childrens = []
    if func(expr):
        return [expr]

    if hasattr(expr, "args"):
        for arg in expr.args:
            if func(arg):
                childrens.append(arg)
            else:
                childrens.extend(xl_get_all_child(arg, func))

        return childrens
    else:
        return childrens


def is_vector_abs(expr):
    answer = False
    if isinstance(expr, Abs):
        answer = True
    return answer


def is_vector2(expr):
    answer = False
    if not isinstance(expr, Add):
        if isinstance(expr, Pow):
            tt = expr.args[0]
            exp = expr.args[1]
            p = r'vector\(.*?\)'
            m = re.findall(p, str(tt))
            if len(m) == 1 and exp == 2:
                answer = True
    return answer


def is_vector_mul(expr):
    answer = False
    p = r'vector\(.{1,2}?\)[*]vector\(.{1,2}?\)'
    m = re.findall(p, str(expr))
    if m:
        answer = True
    return answer


def vector_get_muls(expr):
    p = r'vector\(.{1,3}?\)[*]vector\(.{1,3}?\)'
    m = re.findall(p, str(expr))
    m = set(m)
    m = list(m)
    muls = []
    if m:
        for item in m:
            muls.append(sympify(item))
    return muls


def vector_muls_angle(vector_a, vector_b):
    vector_a_name = vector_a.args[0]
    vector_a_left_p, vector_a_right_p = str(vector_a_name)
    vector_b_name = vector_b.args[0]
    vector_b_left_p, vector_b_right_p = str(vector_b_name)
    angle = None
    if vector_a_left_p == vector_b_left_p:
        angle_name = str('Angle(') + str(vector_a_right_p) + str(',') + str(vector_a_left_p) + str(',') \
                     + str(vector_b_right_p) + str(')')
        angle = sympify(angle_name)
    elif vector_a_right_p == vector_b_left_p:
        angle_name = str('Angle(') + str(vector_a_left_p) + str(',') + str(vector_a_right_p) + str(',') \
                     + str(vector_b_right_p) + str(')')
        angle_name = sympify(angle_name)
        angle = pi - angle_name
    return angle


def vector_expr_sanjiao(expr):
    new_expr = expr
    new_expr = new_expr.expand()
    abs_children = xl_get_all_child(new_expr, is_vector_abs)
    abs_children = set(abs_children)
    abs_children = list(abs_children)
    if abs_children:
        for Abs_Child in abs_children:
            abs_child_value = Abs_Child.args[0]
            if str(abs_child_value.func) == str("vector"):
                abs_child_value_name = abs_child_value.args[0]
                abs_child_value_name_left_p, abs_child_value_name_right_p = str(abs_child_value_name)
                abs_child_value_value = str('line(') + str(abs_child_value_name_left_p) + str(',') + str(
                    abs_child_value_name_right_p) + str(')')
                abs_child_value_value = sympify(abs_child_value_value)
                new_expr = new_expr.subs({Abs_Child: abs_child_value_value})
            else:
                new_expr = new_expr.subs({Abs_Child: sqrt(abs_child_value ** 2)})
    new_expr = new_expr.expand()
    ping_fangs = xl_get_all_child(new_expr, is_vector2)
    ping_fangs = set(ping_fangs)
    ping_fangs = list(ping_fangs)
    if ping_fangs:
        for PingFang in ping_fangs:
            ping_fang_base = PingFang.args[0]
            ping_fang_base_name = ping_fang_base.args[0]
            if len(str(ping_fang_base_name)) == 2:
                ping_fang_base_name_left_p, ping_fang_base_name_right_p = str(ping_fang_base_name)
                ping_fang_base_value = str('line(') + str(ping_fang_base_name_left_p) + str(',') + str(
                    ping_fang_base_name_right_p) + str(')')
                ping_fang_base_value = sympify(ping_fang_base_value)
                ping_fang_value = ping_fang_base_value * ping_fang_base_value
                new_expr = new_expr.subs({PingFang: ping_fang_value})
    muls = vector_get_muls(new_expr)
    muls = set(muls)
    muls = list(muls)
    if muls:
        for item in muls:
            new_item = item
            new_item_value = new_item
            new_item_xiangs = vector_xiangs(new_item)
            if len(new_item_xiangs) == 2:
                vector_a = new_item_xiangs[0]
                vector_b = new_item_xiangs[1]
                for new_item_xiang in new_item_xiangs:
                    new_xiang = new_item_xiang
                    new_xiang_name = new_xiang.args[0]
                    if len(str(new_xiang_name)) == 2:
                        left_p, right_p = str(new_xiang_name)
                        new_xiang_value = str('line(') + str(left_p) + str(',') + str(right_p) + str(')')
                        new_xiang_value = sympify(new_xiang_value)
                        new_item_value = new_item_value.subs({new_xiang: new_xiang_value})
                new_item_angle = vector_muls_angle(vector_a, vector_b)
                new_item_value = new_item_value * cos(new_item_angle)
                new_expr = new_expr.subs({new_item: new_item_value})
    new_expr = new_expr.expand().simplify()
    return new_expr


# 在\\triangle ABC中,AB=2,AC=3,\\overrightarrow{AB}•\\overrightarrow{BC}=1,则|\\overrightarrow{BC}|= ()
class VectorEqsToSanJiaoXing(BaseFunction):
    def solver(self, *args):
        eqs = args[0].sympify()
        neqs = []
        veqs = []
        for eq in eqs:
            expr = eq[0] - eq[1]
            if str(expr).find(str("vector")) >= 0:
                veqs.append(eq)
            else:
                neqs.append(eq)
        if veqs:
            for Vindex, Veq in enumerate(veqs):
                vleft = Veq[0]
                vleft = vector_expr_sanjiao(vleft)
                vleft = vleft.expand().simplify()
                vright = Veq[1]
                vright = vector_expr_sanjiao(vright)
                vright = vright.expand().simplify()
                veqs[Vindex][0] = vleft
                veqs[Vindex][1] = vright
        eqs = []
        eqs.extend(neqs)
        eqs.extend(veqs)
        self.output.append(BaseSineqs(eqs))
        return self


# 在Rt \\triangle ABC中,\\angle C =90°,AC=4,则\\overrightarrow{AB}•\\overrightarrow{AC}等于()
class VectorEqToSanJiaoXing(BaseFunction):
    def solver(self, *args):
        if isinstance(args[0], BaseGeoEq):
            l_expr, r_expr = map(sympify, args[0].value)
            eq = [l_expr, r_expr]
        else:
            eq = args[0].sympify()
        expr = eq[0] - eq[1]
        if str(expr).find(str("vector")) >= 0:
            left = eq[0]
            left = vector_expr_sanjiao(left)
            left = left.expand().simplify()
            right = eq[1]
            right = vector_expr_sanjiao(right)
            right = right.expand().simplify()
            self.output.append(BaseSineqs([[left, right]]))
        else:
            self.output.append(BaseSineqs([eq]))
        return self


# 在\\triangle ABC中,AB=2,AC=3,\\overrightarrow{AB}•\\overrightarrow{BC}=1,则|\\overrightarrow{BC}|= ()
class VectorExpressToSanJiaoXing(BaseFunction):
    def solver(self, *args):
        expr = args[0].sympify()
        new_expr = vector_expr_sanjiao(expr)
        self.output.append(BasePoly(new_expr))
        return self


# D为边BC的中点
class VectorZhongDianToSanJiaoXing(BaseFunction):
    def solver(self, *args):
        middle = args[0].sympify()
        line = args[1].sympify()
        left, right = line.args[0]
        left_line = str('line(') + str(left) + str(',') + str(middle) + str(')')
        right_line = str('line(') + str(middle) + str(',') + str(right) + str(')')
        self.output.append(BaseSineqs([[left_line, right_line]]))
        return self


if __name__ == '__main__':
    pass
